package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.AlbumAttributeValueService;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private AlbumAttributeValueMapper albumAttributeValueMapper;

	@Autowired
	private AlbumAttributeValueService albumAttributeValueService;

    @Autowired
    private RabbitService rabbitService;

	@Autowired
	private StringRedisTemplate redisTemplate;


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {

		AlbumInfoServiceImpl proxyObject =(AlbumInfoServiceImpl) AopContext.currentProxy();
		//入库tingshu_album 表（album_info album_attribute_value）
		Long userId = AuthContextHolder.getUserId();

		//1.保存专辑的基本信息（album_info表中插入数据）
		//实体类专门用来和数据库列做映射
		AlbumInfo albumInfo = new AlbumInfo();
		BeanUtils.copyProperties(albumInfoVo,albumInfo);

		albumInfo.setUserId(userId); // 额外赋值一次（userId）
		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS); //默认审核通过（todo 对接后续系统 ）

		//获取专辑的付费类型（0101（免费） 0102（vip免费） 0103（付费））
		String payType = albumInfoVo.getPayType();
		if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(payType)){
			//默认给这个专辑设置5集免费声音
			albumInfo.setTracksForFree(5);
		}
		int insert = albumInfoMapper.insert(albumInfo);
		log.info("保存专辑基本信息：{}",insert > 0 ? "success":"fail");

		//2.保存专辑的标签信息（album_attribute_value表中插入数据）

		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList(); //获取先择的标签信息

		List<AlbumAttributeValue> attributeValues = albumAttributeValueVoList.stream().map(albumAttributeValueVo -> {
			AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
			albumAttributeValue.setAlbumId(albumInfo.getId());
			albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());  //专辑的属性Id
			albumAttributeValue.setValueId(albumAttributeValueVo.getValueId()); //属性值Id
			return albumAttributeValue;
		}).collect(Collectors.toList());

		if (!CollectionUtils.isEmpty(attributeValues)){
			boolean b = albumAttributeValueService.saveBatch(attributeValues);
			log.info("保存专辑标签信息：{}",b ? "success":"fail");
		}

		//3.保存专辑的统计（album_stat）
//		saveAlbumStat(albumInfo.getId());
		proxyObject.saveAlbumStat(albumInfo.getId());

		//将专辑同步到es中(同步rpc、异步消息队列)
		String isOpen = albumInfoVo.getIsOpen();
		if ("1".equals(isOpen)){
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER,albumInfo.getId().toString());
			log.info("专辑微服务发送消息到专辑上架队列成功");
		}


	}

	@Override
	public void findUserAlbumPage(IPage<AlbumListVo> page, AlbumInfoQuery albumInfoQuery) {
		albumInfoMapper.findUserAlbumPage(page,albumInfoQuery);
	}

	@Override
	public AlbumInfo getAlbumInfo(Long albumId) {
		AlbumInfo albumInfo = getById(albumId);
		if (albumInfo == null){
			throw new GuiguException(201,"该专辑不存在");
		}
		List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
		albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);

		return albumInfo;

	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {

//		//方案一：先删缓存 再更新数据库 在cdc中异步删除缓存 在cdc中异步再次删除缓存+消息队列重试机制
//		String cacheKey = RedisConstant.CACHE_INFO_PREFIX + albumId;
//		redisTemplate.delete(cacheKey);


		//1.修改基本信息
		AlbumInfo albumInfo = getById(albumId);
		if (albumInfo == null){
			throw  new GuiguException(201,"该专辑不存在");

		}
		BeanUtils.copyProperties(albumInfoVo,albumInfo); //有的属性直接拷贝过去，vo没有的属性用老的AlbumInfo
		if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)){
			albumInfo.setPrice(new BigDecimal("0.00"));
			albumInfo.setDiscount(new BigDecimal("-1.00"));
			albumInfo.setVipDiscount(new BigDecimal("-1.00"));
			albumInfo.setTracksForFree(0);

		}else{
			albumInfo.setTracksForFree(5);
		}


		int i = albumInfoMapper.updateById(albumInfo);
		log.info("修改专辑的基本信息：{}",i > 0 ? "success":"fail");

		//2.修改专辑的标签信息
		//2.1 删除该专辑的老标签信息
		LambdaQueryWrapper<AlbumAttributeValue> albumAttributeValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
		albumAttributeValueLambdaQueryWrapper.eq(AlbumAttributeValue::getAlbumId,albumId);
		int delete = albumAttributeValueMapper.delete(albumAttributeValueLambdaQueryWrapper);
		log.info("删除专辑标签信息：{}",delete > 0 ? "success":"fail");

		//2.2查询该专辑的新标签信息
		List<AlbumAttributeValue> attributeValues = albumInfoVo.getAlbumAttributeValueVoList().stream().map(albumAttributeValueVo -> {
			AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
			albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
			albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
			albumAttributeValue.setAlbumId(albumId);
			return albumAttributeValue;
		}).collect(Collectors.toList());

		if (!CollectionUtils.isEmpty(attributeValues)){
			boolean b = albumAttributeValueService.saveBatch(attributeValues);
			log.info("保存专辑标签信息：{}",b ? "success":"fail");
		}
		//专辑是否公开(要不要同步到es在首页显示)
		String isOpen = albumInfoVo.getIsOpen();
		if ("1".equals(isOpen)){
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_UPPER,albumInfo.getId().toString());
			log.info("专辑微服务发送消息到专辑上架队列成功");
		}else {
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER,albumInfo.getId().toString());
			log.info("专辑微服务发送消息到专辑下架队列成功");
		}

		//方案二：先更新数据库 在cdc中删除缓存 + 消息队列重删机制




	}

	@Override
	public void removeAlbumInfo(Long albumId) {
		//1.删除专辑的基本信息
		//查询专辑下是否有声音
		Long count = trackInfoMapper.selectCount(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, albumId));
		if (count > 0 ){
			throw new GuiguException(201,"该专辑下还有声音，请勿删除");
		}
		int i = albumInfoMapper.deleteById(albumId);
		log.info("删除专辑的基本信息：{}",i > 0 ? "success" : "fail");
		//2.删除专辑的标签信息
		int delete = albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
		log.info("删除专辑的标签信息：{}",delete > 0 ? "success" : "fail");
		//3.删除专辑的统计信息
		int delete1 = albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, albumId));
		log.info("删除专辑的统计信息：{}",delete1 > 0 ? "success" : "fail");

		//4.将专辑从es中删除
		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM, MqConst.ROUTING_ALBUM_LOWER,albumId.toString());
		log.info("专辑微服务发送消息到专辑下架队列成功");

	}

	@Override
	public List<AlbumInfo> findUserAllAlbumList() {
		Long userId = AuthContextHolder.getUserId();
		LambdaQueryWrapper<AlbumInfo> albumInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
		albumInfoLambdaQueryWrapper.eq(AlbumInfo::getUserId,userId);
		return albumInfoMapper.selectList(albumInfoLambdaQueryWrapper);

	}

	@Override
	public AlbumStatVo getAlbumStat(Long albumId) {
		return albumStatMapper.getAlbumStat(albumId);

	}

	@Override
	public List<Long> getAlbumInfoIdList() {
		List<AlbumInfo> albumInfos = albumInfoMapper.selectList(null);
		List<Long> albumIds = albumInfos.stream().map(AlbumInfo::getId).collect(Collectors.toList());
		return albumIds;
	}

	@Override
	public AlbumInfo getAlbumInfoByTrackId(Long trackId) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		if (trackInfo == null){
			throw new GuiguException(201,"该声音不存在");
		}
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		if (albumInfo == null){
			throw new GuiguException(201,"该专辑不存在");
		}
		return albumInfo;
	}


	@Transactional
	public void saveAlbumStat(Long albumId) {
		List<String> albumStatus = new ArrayList<>();
		albumStatus.add(SystemConstant.ALBUM_STAT_PLAY);
		albumStatus.add(SystemConstant.ALBUM_STAT_SUBSCRIBE);
		albumStatus.add(SystemConstant.ALBUM_STAT_BROWSE);
		albumStatus.add(SystemConstant.ALBUM_STAT_COMMENT);

		for (String status : albumStatus) {
			AlbumStat albumStat = new AlbumStat();
			albumStat.setAlbumId(albumId);
			albumStat.setStatType(status);
			albumStat.setStatNum(0);
			albumStatMapper.insert(albumStat);
		}

	}
}
